#ifndef _CAMERA_H_
#define _CAMERA_H_

#include "config.h"
#include "geometry.h"
#include "matrix4x4.h"
#include "ray.h"
#include "random_number_generator.h"
#include "sampler.h"
#include "film.h"

class Camera{
public:
	Camera(const transform_t& camera_to_world, Film* f):film_(f){transform_assign(camera_to_world_,camera_to_world);}
	void GenerateRay(const camera_sample_t& camera_sample, ray_differential_t *ray,
		float *weight)const;	
	virtual void GenerateRay(const camera_sample_t& camera_sample, ray_t *ray, float *weight)const = 0;
	virtual ~Camera(){}
protected:
	const Film* GetFilm(){return film_;}
	const transform_t& CameraToWorld()const{return camera_to_world_;}
private:
	transform_t camera_to_world_;
	Film* film_;
};

struct screen_window_t{
	explicit screen_window_t(float frame_aspect_ratio);
	void set_window(float xmin,float xmax,float ymin,float ymax);
	float x_min,x_max;//[-1,1]
	float y_min,y_max;//[-1,1]
};
class ProjectiveCamera:public Camera
{
public:
	ProjectiveCamera(const transform_t& camera_to_world,const transform_t& proj, const screen_window_t& screen_window,Film *film);
protected:
	const transform_t& CameraToScreen()const{return camera_to_screen_;}
	const transform_t& RasterToCamera()const{return raster_to_camera_;}
	const transform_t& RasterToScreen()const{return raster_to_screen_;}
	const transform_t& ScreenToRaster()const{return screen_to_raster_;}
private:
	transform_t camera_to_screen_,raster_to_camera_;
	transform_t raster_to_screen_,screen_to_raster_;
};
#endif